﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AddIn.EA.Framework;
using AddIn.EA.Architecture.CatalogService.BusinessEntity;
using System.IO;
using AddIn.EA.Architecture.Validation.BusinessEntity;

namespace AddIn.EA.Architecture.CatalogService.BusinessLogic
{
    public class MethodXml
    {
        private RepositoryManager repository { get; set; }
        private Package service { get; set; }

        public MethodXml(RepositoryManager repository, Package service)
        {
            this.repository = repository;
            this.service = service;
        }

        /// <summary>
        /// Gera os XMLs dos metodos
        /// </summary>
        /// <param name="fileAssembly"></param>
        /// <returns></returns>
        public List<MemberBase> GetMethodXmls(string fileAssembly)
        {
            var interfaceXml = new InterfaceXml(this.repository, this.service);
            var interfaceElements = interfaceXml.GetInterfaceElements();
            var methodXmls = new List<MemberBase>();

            // Percorrer todas interfaces do servico
            foreach (var interfaceElement in interfaceElements)
            {
                // Percorrer os metodos da interface
                foreach (var methodElement in interfaceElement.Methods
                    .Where(x => string.IsNullOrEmpty(x.Stereotype)))
                {
                    // Adicionar metodo
                    var methodXml = new MemberMethod();
                    methodXml.ProjectGUID = this.repository.ProjectGUID;
                    methodXml.Name = methodElement.GetFullName(fileAssembly);
                    methodXml.Summary = methodElement.GetNotes();

                    // Adicionar os parametros do metodo
                    if (methodElement.Parameters != null && methodElement.Parameters.Count > 0)
                    {
                        methodXml.Params = new List<Param>();

                        foreach (var paramElement in methodElement.Parameters)
                        {
                            methodXml.Params.Add(new Param
                            {
                                Name = paramElement.Name,
                                Description = paramElement.Notes
                            });
                        };
                    }

                    // Adicionar retorno
                    methodXml.Returns = methodElement.GetReturns();

                    if (methodElement.PreConditions != null && methodElement.PreConditions.Count > 0)
                    {
                        // Adicionar transacional
                        var transacional = (from pc in methodElement.PreConditions
                                            where pc.Type == "Transacional"
                                            select pc).SingleOrDefault();

                        Item itemTransacional = null;
                        if (transacional != null)
                        {
                            itemTransacional = new Item
                            {
                                Description = transacional.Type + ": " + transacional.Name
                            };
                        }

                        // Adicionar exceções
                        var excecoes = (from pc in methodElement.PreConditions
                                        where pc.Type == "ValidationFault" ||
                                              pc.Type == "BusinessFault"
                                        select pc).ToList();

                        Item itemExcecoes = null;
                        if (excecoes != null && excecoes.Count > 0)
                        {
                            var listExcecoes = new List<Item>();

                            foreach (var excecao in excecoes)
                            {
                                // Exceção
                                listExcecoes.Add(new Item
                                {
                                    Term = new List<string> { excecao.Name, excecao.Type },
                                    Description = excecao.Notes
                                });
                            }

                            // Cabeçalho
                            itemExcecoes = new Item
                            {
                                Description = "Exceções de negócio:",
                                List = new ListTable
                                {
                                    ListHeader = new Item
                                    {
                                        Term = new List<string> { "ID", "Tipo" },
                                        Description = "Condição"
                                    },
                                    Item = listExcecoes
                                        .OrderBy(x => x.Term[1])
                                        .ToList()
                                }
                            };
                        }

                        methodXml.Remarks = new Remarks
                        {
                            List = new ListBullet
                            {
                                Item = new List<Item>
                                {
                                    itemTransacional,
                                    itemExcecoes
                                }
                            }
                        };
                    }

                    methodXmls.Add(methodXml);
                }
            }

            return methodXmls;
        }

    }
}
